import { statement,Scope } from "./cfg";

export class DDG{
    N:number;
    in:number[];
    v:Array<number>[];
    ident:Array<String>[];
    
    constructor(N:number){
        this.N = N;
        this.in = new Array<number>(N+10).fill(0);
        this.v = new Array<Array<number>>(N+10);
        this.ident = new Array<Array<String>>(N+10);
        for(let i=0;i<=N+9;i++){
            this.v[i]=new Array<number>;
            this.ident[i]=new Array<String>;
        }
    }
    addEdge(u:number,v:number,ident:String){
        this.v[u].push(v);
        this.ident[u].push(ident);
        console.log(u,v,ident);
    }
}
export class DDGGEN{
    N:number;
    st:number;
    stmArray:statement[];
    scopes:Scope[];
    v:Array<number>[];
    ddg:DDG;
    ved:number[];

    constructor(N:number, st:number, stmArray:statement[], scopes:Scope[]){
        this.N = N;
        this.st = st;
        this.stmArray = stmArray;
        this.scopes = scopes;
        this.v = new Array<Array<number>>(N+10);
        for(let i=0;i<=N+9;i++){
            this.v[i]=new Array<number>;
        }
        this.ddg = new DDG(N);
        this.ved=new Array<number>(N+10).fill(0);

        for(let st of stmArray){
            console.log(st.code);
            console.log(st.use);
            console.log(st.def);
        }
    }
    addEdge(u:number,v:number){
        this.v[v].push(u);//建反图
    }
    scopeHasIdent(scope:Scope, ident:String):boolean{
        for(var str of scope.variable){
            if(str == ident)return true;
        }
        return false;
    }
    dfs(st:number,x:number,idents:Set<String>){
        this.ved[x]=1;
        // 如果st的某个use在x的def中出现，ddg连一条从x到st的边,ident为此变量名,然后删去此ident
        let down:Set<String>=new Set<String>;
        for(var ident of idents){
            down.add(ident);
        }
        if(st!=x){
            let xId = this.stmArray[x].scopeID, stId = this.stmArray[st].scopeID;
            let xScope = this.scopes[xId], stScope = this.scopes[stId];
            for(var ident of idents){
                // scope相同或者x的层数小于st
                if(xId==stId || xScope.level<stScope.level || !this.scopeHasIdent(xScope, ident)){
                    if(this.stmArray[x].def.has(ident)){
                        this.ddg.addEdge(x,st,ident);
                        down.delete(ident); 
                    }
                    else if(this.stmArray[x].defspecial.has(ident)){
                        this.ddg.addEdge(x,st,ident);
                    }
                }
            }
        }
        for(var y of this.v[x])
        if(this.ved[y]==0){
            this.dfs(st,y,down);
        }
    }
    init(){
        for(var i=0;i<=this.N+9;i++){
            if(this.stmArray[i]==undefined)continue;
            this.ved=new Array<number>(this.N+10).fill(0);
            // 将i的use加入idents
            var idents:Set<String> = this.stmArray[i].use;
            this.dfs(i, i, idents);
        }
    }
    getDDG():DDG{
        return this.ddg;
    }
}